home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / app / scale.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-01-15  |  6.7 KB  |  266 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22.  
  23. #include <glib.h>
  24.  
  25. #include "apptypes.h"
  26.  
  27. #include "appenv.h"
  28. #include "gdisplay.h"
  29. #include "gdisplay_ops.h"
  30. #include "gimprc.h"
  31. #include "nav_window.h"
  32. #include "scale.h"
  33. #include "tools.h"
  34.  
  35. void
  36. bounds_checking (GDisplay *gdisp)
  37. {
  38.   gint sx, sy;
  39.  
  40.   sx = SCALEX (gdisp, gdisp->gimage->width);
  41.   sy = SCALEY (gdisp, gdisp->gimage->height);
  42.  
  43.   gdisp->offset_x = CLAMP (gdisp->offset_x, 0,
  44.                LOWPASS (sx - gdisp->disp_width));
  45.  
  46.   gdisp->offset_y = CLAMP (gdisp->offset_y, 0,
  47.                LOWPASS (sy - gdisp->disp_height));
  48. }
  49.  
  50.  
  51. void
  52. resize_display (GDisplay *gdisp,
  53.         gboolean  resize_window,
  54.         gboolean  redisplay)
  55. {
  56.   /* freeze the active tool */
  57.   active_tool_control (PAUSE, (void *) gdisp);
  58.  
  59.   if (resize_window)
  60.     gdisplay_shrink_wrap (gdisp);
  61.  
  62.   bounds_checking (gdisp);
  63.   setup_scale (gdisp);
  64.  
  65.   if (resize_window || redisplay)
  66.     {
  67.       gdisplay_expose_full (gdisp);
  68.       gdisplays_flush ();
  69.       /* title may have changed if it includes the zoom ratio */
  70.       gdisplay_update_title (gdisp);
  71.     }
  72.  
  73.   /* re-enable the active tool */
  74.   active_tool_control (RESUME, (void *) gdisp);
  75. }
  76.  
  77.  
  78. void
  79. shrink_wrap_display (GDisplay *gdisp)
  80. {
  81.   /* freeze the active tool */
  82.   active_tool_control (PAUSE, (void *) gdisp);
  83.  
  84.   gdisplay_shrink_wrap (gdisp);
  85.  
  86.   bounds_checking (gdisp);
  87.   setup_scale (gdisp);
  88.  
  89.   gdisplay_expose_full (gdisp);
  90.   gdisplays_flush ();
  91.  
  92.   /* re-enable the active tool */
  93.   active_tool_control (RESUME, (void *) gdisp);
  94. }
  95.  
  96.  
  97. void
  98. change_scale (GDisplay *gdisp,
  99.           ZoomType  zoom_type)
  100. {
  101.   guchar scalesrc, scaledest;
  102.   gdouble offset_x, offset_y;
  103.  
  104.   /* user zoom control, so resolution versions not needed -- austin */
  105.   scalesrc = SCALESRC (gdisp);
  106.   scaledest = SCALEDEST (gdisp);
  107.  
  108.   offset_x = gdisp->offset_x + (gdisp->disp_width / 2.0);
  109.   offset_y = gdisp->offset_y + (gdisp->disp_height / 2.0);
  110.  
  111.   offset_x *= ((double) scalesrc / (double) scaledest);
  112.   offset_y *= ((double) scalesrc / (double) scaledest);
  113.  
  114.   switch (zoom_type)
  115.     {
  116.     case ZOOMIN :
  117.       if (scalesrc > 1)
  118.     scalesrc--;
  119.       else
  120.     if (scaledest < 0x10)
  121.       scaledest++;
  122.     else
  123.       return;
  124.       break;
  125.  
  126.     case ZOOMOUT :
  127.       if (scaledest > 1)
  128.     scaledest--;
  129.       else
  130.     if (scalesrc < 0x10)
  131.       scalesrc++;
  132.     else
  133.       return;
  134.       break;
  135.  
  136.     default :
  137.       scalesrc = zoom_type % 100;
  138.       if (scalesrc < 1)
  139.     scalesrc = 1;
  140.       else if (scalesrc > 0x10)
  141.     scalesrc = 0x10;
  142.       scaledest = zoom_type / 100;
  143.       if (scaledest < 1)
  144.     scaledest = 1;
  145.       else if (scaledest > 0x10)
  146.     scaledest = 0x10;
  147.       break;
  148.     }
  149.  
  150.   gdisp->scale = (scaledest << 8) + scalesrc;
  151.  
  152.   /*  set the offsets  */
  153.   offset_x *= ((double) scaledest / (double) scalesrc);
  154.   offset_y *= ((double) scaledest / (double) scalesrc);
  155.   
  156.   gdisp->offset_x = (int) (offset_x - (gdisp->disp_width / 2));
  157.   gdisp->offset_y = (int) (offset_y - (gdisp->disp_height / 2));
  158.   
  159.   /*  resize the image  */
  160.   resize_display (gdisp, allow_resize_windows, TRUE);
  161. }
  162.  
  163.  
  164. /* scale image coord to realworld units (cm, inches, pixels) */
  165. /* 27/Feb/1999 I tried inlining this, but the result was slightly
  166.  * slower (poorer cache locality, probably) -- austin */
  167. static gdouble
  168. img2real (GDisplay *gdisp,
  169.       gboolean  xdir,
  170.       gdouble   a)
  171. {
  172.   gdouble res;
  173.  
  174.   if (gdisp->dot_for_dot)
  175.     return a;
  176.  
  177.   if (xdir)
  178.     res = gdisp->gimage->xresolution;
  179.   else
  180.     res = gdisp->gimage->yresolution;
  181.  
  182.   return a * gimp_unit_get_factor (gdisp->gimage->unit) / res;
  183. }
  184.  
  185.  
  186. void
  187. setup_scale (GDisplay *gdisp)
  188. {
  189.   GtkRuler *hruler;
  190.   GtkRuler *vruler;
  191.   gfloat sx, sy;
  192.   gfloat stepx, stepy;
  193.  
  194.   sx = SCALEX (gdisp, gdisp->gimage->width);
  195.   sy = SCALEY (gdisp, gdisp->gimage->height);
  196.   stepx = SCALEFACTOR_X (gdisp);
  197.   stepy = SCALEFACTOR_Y (gdisp);
  198.  
  199.   gdisp->hsbdata->value = gdisp->offset_x;
  200.   gdisp->hsbdata->upper = sx;
  201.   gdisp->hsbdata->page_size = MIN (sx, gdisp->disp_width);
  202.   gdisp->hsbdata->page_increment = (gdisp->disp_width / 2);
  203.   gdisp->hsbdata->step_increment = stepx;
  204.  
  205.   gdisp->vsbdata->value = gdisp->offset_y;
  206.   gdisp->vsbdata->upper = sy;
  207.   gdisp->vsbdata->page_size = MIN (sy, gdisp->disp_height);
  208.   gdisp->vsbdata->page_increment = (gdisp->disp_height / 2);
  209.   gdisp->vsbdata->step_increment = stepy;
  210.  
  211.   gtk_signal_emit_by_name (GTK_OBJECT (gdisp->hsbdata), "changed");
  212.   gtk_signal_emit_by_name (GTK_OBJECT (gdisp->vsbdata), "changed");
  213.  
  214.   hruler = GTK_RULER (gdisp->hrule);
  215.   vruler = GTK_RULER (gdisp->vrule);
  216.  
  217.   hruler->lower = 0;
  218.   hruler->upper = img2real (gdisp, TRUE, FUNSCALEX (gdisp, gdisp->disp_width));
  219.   hruler->max_size = img2real (gdisp, TRUE, MAX (gdisp->gimage->width,
  220.                          gdisp->gimage->height));
  221.  
  222.   vruler->lower = 0;
  223.   vruler->upper = img2real(gdisp, FALSE, FUNSCALEY(gdisp, gdisp->disp_height));
  224.   vruler->max_size = img2real (gdisp, FALSE, MAX (gdisp->gimage->width,
  225.                           gdisp->gimage->height));
  226.  
  227.   if (sx < gdisp->disp_width)
  228.     {
  229.       gdisp->disp_xoffset = (gdisp->disp_width - sx) / 2;
  230.       hruler->lower -= img2real(gdisp, TRUE,
  231.                 FUNSCALEX (gdisp, (double) gdisp->disp_xoffset));
  232.       hruler->upper -= img2real(gdisp, TRUE,
  233.                 FUNSCALEX (gdisp, (double) gdisp->disp_xoffset));
  234.     }
  235.   else
  236.     {
  237.       gdisp->disp_xoffset = 0;
  238.       hruler->lower += img2real (gdisp, TRUE,
  239.                  FUNSCALEX (gdisp, (double) gdisp->offset_x));
  240.       hruler->upper += img2real (gdisp, TRUE,
  241.                  FUNSCALEX (gdisp, (double) gdisp->offset_x));
  242.     }
  243.  
  244.   if (sy < gdisp->disp_height)
  245.     {
  246.       gdisp->disp_yoffset = (gdisp->disp_height - sy) / 2;
  247.       vruler->lower -= img2real(gdisp, FALSE,
  248.                 FUNSCALEY (gdisp, (double) gdisp->disp_yoffset));
  249.       vruler->upper -= img2real(gdisp, FALSE,
  250.                 FUNSCALEY (gdisp, (double) gdisp->disp_yoffset));
  251.     }
  252.   else
  253.     {
  254.       gdisp->disp_yoffset = 0;
  255.       vruler->lower += img2real (gdisp, FALSE,
  256.                  FUNSCALEY (gdisp, (double) gdisp->offset_y));
  257.       vruler->upper += img2real (gdisp, FALSE,
  258.                  FUNSCALEY (gdisp, (double) gdisp->offset_y));
  259.     }
  260.  
  261.   gtk_widget_queue_draw (GTK_WIDGET (hruler));
  262.   gtk_widget_queue_draw (GTK_WIDGET (vruler));
  263.  
  264.   nav_window_update_window_marker (gdisp->window_nav_dialog);
  265. }
  266.